home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.7 / tcpdump- / tcpdump-richard-1.7 / tcpdump-3.0 / tcpdump.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-24  |  9.1 KB  |  444 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. char copyright[] =
  23.     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994\nThe Regents of the University of California.  All rights reserved.\n";
  24. static  char rcsid[] =
  25.     "@(#)$Header: tcpdump.c,v 1.93 94/06/10 17:01:44 mccanne Exp $ (LBL)";
  26. #endif
  27.  
  28. /*
  29.  * tcpdump - monitor tcp/ip traffic on an ethernet.
  30.  *
  31.  * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
  32.  * Mercilessly hacked and occasionally improved since then via the
  33.  * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
  34.  */
  35.  
  36. #include <sys/types.h>
  37. #include <sys/time.h>
  38.  
  39. #include <netinet/in.h>
  40.  
  41. #include <pcap.h>
  42. #include <signal.h>
  43. #include <stdio.h>
  44. #include <string.h>
  45.  
  46. #include "interface.h"
  47. #include "addrtoname.h"
  48.  
  49. #ifdef __STDC__
  50. #include <stdlib.h>
  51. #endif
  52. #include <unistd.h>
  53.  
  54. int fflag;            /* don't translate "foreign" IP address */
  55. int nflag;            /* leave addresses as numbers */
  56. int Nflag;            /* remove domains from printed host names */
  57. int pflag;            /* don't go promiscuous */
  58. int qflag;            /* quick (shorter) output */
  59. int tflag = 1;            /* print packet arrival time */
  60. int eflag;            /* print ethernet header */
  61. int vflag;            /* verbose */
  62. int xflag;            /* print packet in hex */
  63. int Dflag;            /* print data in ASCII */
  64. int Oflag = 1;            /* run filter code optimizer */
  65. int Sflag;            /* print raw TCP sequence numbers */
  66. int packettype;
  67.  
  68. int dflag;            /* print filter code */
  69.  
  70. char *program_name;
  71.  
  72. int thiszone;
  73.  
  74. SIGRET cleanup(int);
  75. extern void bpf_dump(struct bpf_program *, int);
  76.  
  77. /* Length of saved portion of packet. */
  78. int snaplen = DEFAULT_SNAPLEN;
  79.  
  80. struct printer {
  81.     pcap_handler f;
  82.     int type;
  83. };
  84.  
  85. static struct printer printers[] = {
  86.     { ether_if_print,    DLT_EN10MB },
  87.     { sl_if_print,        DLT_SLIP },
  88.     { ppp_if_print,        DLT_PPP },
  89.     { fddi_if_print,    DLT_FDDI },
  90.     { null_if_print,    DLT_NULL },
  91.     { NULL,            0 },
  92. };
  93.  
  94. static pcap_handler
  95. lookup_printer(int type)
  96. {
  97.     struct printer *p;
  98.  
  99.     for (p = printers; p->f; ++p)
  100.         if (type == p->type)
  101.             return p->f;
  102.  
  103.     error("unknown data link type 0x%x", type);
  104.     /* NOTREACHED */
  105. }
  106.  
  107. #ifdef __osf__
  108. #include <sys/sysinfo.h>
  109. #include <sys/proc.h>
  110. void
  111. abort_on_misalignment()
  112. {
  113.     int buf[2];
  114.     
  115.     buf[0] = SSIN_UACPROC;
  116.     buf[1] = UAC_SIGBUS;
  117.     if (setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0) < 0) {
  118.         perror("setsysinfo");
  119.         exit(1);
  120.     }
  121. }
  122.  
  123. #endif
  124.  
  125. static pcap_t *pd;
  126.  
  127. int
  128. main(int argc, char **argv)
  129. {
  130.     register int cnt, op;
  131.     u_long localnet, netmask;
  132.     register char *cp, *infile, *cmdbuf; 
  133.     char *device, *RFileName, *WFileName, *hosts;
  134.     pcap_handler printer;
  135.     struct bpf_program fcode;
  136.     pcap_dumper_t *p;
  137.     u_char *pcap_userdata;
  138.     struct pcap_stat stat;
  139.     char errbuf[PCAP_ERRBUF_SIZE];
  140.     int format = FORMAT_TCPDUMP;
  141.  
  142.     extern char *optarg;
  143.     extern int optind, opterr;
  144.  
  145. #ifdef __osf__
  146.     abort_on_misalignment();
  147. #endif
  148.  
  149.     cnt = -1;
  150.     device = NULL;
  151.     infile = NULL;
  152.     RFileName = NULL;
  153.     WFileName = NULL;
  154.     hosts = NULL;
  155.     if ((cp = strrchr(argv[0], '/')) != NULL)
  156.         program_name = cp + 1;
  157.     else
  158.         program_name = argv[0];
  159.  
  160.     opterr = 0;
  161.     while ((op = getopt(argc, argv, "c:dDefF:i:lnNOpqr:R:s:StT:vw:W:xY")) != EOF)
  162.         switch (op) {
  163.         case 'c':
  164.             cnt = atoi(optarg);
  165.             break;
  166.  
  167.         case 'd':
  168.             ++dflag;
  169.             break;
  170.  
  171.         case 'D':
  172.             ++Dflag;
  173.             break;
  174.  
  175.         case 'e':
  176.             ++eflag;
  177.             break;
  178.  
  179.         case 'f':
  180.             ++fflag;
  181.             break;
  182.  
  183.         case 'F':
  184.             infile = optarg;
  185.             break;
  186.  
  187.         case 'i':
  188.             device = optarg;
  189.             break;
  190.  
  191.         case 'l':
  192.             setlinebuf(stdout);
  193.             break;
  194.  
  195.         case 'n':
  196.             ++nflag;
  197.             break;
  198.  
  199.         case 'N':
  200.             ++Nflag;
  201.             break;
  202.  
  203.         case 'O':
  204.             Oflag = 0;
  205.             break;
  206.  
  207.         case 'p':
  208.             ++pflag;
  209.             break;
  210.  
  211.         case 'q':
  212.             ++qflag;
  213.             break;
  214.  
  215.         case 'r':
  216.             RFileName = optarg;
  217.             break;
  218.  
  219.         case 'R':
  220.             hosts = optarg;
  221.             break;
  222.  
  223.         case 's':
  224.             snaplen = atoi(optarg);
  225.             break;
  226.  
  227.         case 'S':
  228.             ++Sflag;
  229.             break;
  230.  
  231.         case 't':
  232.             --tflag;
  233.             break;
  234.  
  235.         case 'T':
  236.             if (strcasecmp(optarg, "vat") == 0)
  237.                 packettype = 1;
  238.             else if (strcasecmp(optarg, "wb") == 0)
  239.                 packettype = 2;
  240.             else if (strcasecmp(optarg, "rpc") == 0)
  241.                 packettype = 3;
  242.             else if (strcasecmp(optarg, "rtp") == 0)
  243.                 packettype = 4;
  244.             else
  245.                 error("unknown packet type `%s'", optarg);
  246.             break;
  247.  
  248.         case 'v':
  249.             ++vflag;
  250.             break;
  251.  
  252.         case 'w':
  253.             WFileName = optarg;
  254.             format = FORMAT_TCPDUMP;
  255.             break;
  256.         case 'W':
  257.             WFileName = optarg;
  258.             format = FORMAT_SNOOP2;
  259.             break;
  260. #ifdef YYDEBUG
  261.         case 'Y':
  262.             {
  263.             extern int yydebug;
  264.             yydebug = 1;
  265.             }
  266.             break;
  267. #endif
  268.         case 'x':
  269.             ++xflag;
  270.             break;
  271.  
  272.         default:
  273.             usage();
  274.             /* NOTREACHED */
  275.         }
  276.  
  277.     if (tflag > 0)
  278.         thiszone = gmt2local();
  279.  
  280.     if (RFileName != NULL) {
  281.         /*
  282.          * We don't need network access, so set it back to the user id.
  283.          * Also, this prevents the user from reading anyone's
  284.          * trace file.
  285.          */
  286.         setuid(getuid());
  287.  
  288.         pd = pcap_open_offline(RFileName, snaplen, errbuf);
  289.         if (pd == NULL)
  290.             error(errbuf);
  291.         localnet = 0;
  292.         netmask = 0;
  293.         if (fflag != 0)
  294.             error("-f and -r options are incompatible");
  295.     } else {
  296.         if (device == NULL) {
  297.             device = pcap_lookupdev(errbuf);
  298.             if (device == NULL)
  299.                 error(errbuf);
  300.         }
  301.         pd = pcap_open_live(device, snaplen, !pflag, 1000, errbuf);
  302.         if (pd == NULL)
  303.             error(errbuf);
  304.         if (pcap_lookupnet(device, &localnet, &netmask, errbuf) < 0)
  305.             error(errbuf);
  306.         /*
  307.          * Let user own process after socket has been opened.
  308.          */
  309.         setuid(getuid());
  310.     }
  311.     if (infile)
  312.         cmdbuf = read_infile(infile);
  313.     else
  314.         cmdbuf = copy_argv(&argv[optind]);
  315.  
  316.     if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
  317.         error(pcap_geterr(pd));
  318.     if (dflag) {
  319.         bpf_dump(&fcode, dflag);
  320.         exit(0);
  321.     }
  322.  
  323.     init_addrtoname(fflag, localnet, netmask, hosts);
  324.  
  325.     (void)signal(SIGTERM, cleanup);
  326.     (void)signal(SIGINT, cleanup);
  327.     (void)signal(SIGHUP, cleanup);
  328.  
  329.     if (pcap_setfilter(pd, &fcode) < 0)
  330.         error(pcap_geterr(pd));
  331.     if (WFileName) {
  332.         p = pcap_dump_open(pd, WFileName, format);
  333.         if (p == NULL)
  334.             error(pcap_geterr(pd));
  335.         printer = pcap_dump;
  336.         pcap_userdata = (u_char *)p;
  337.     } else {
  338.         printer = lookup_printer(pcap_datalink(pd));
  339.         pcap_userdata = 0;
  340.     }
  341.     if (RFileName == NULL) {
  342.         fprintf(stderr, "%s: listening on %s\n", program_name, device);
  343.         fflush(stderr);
  344.     }
  345.     
  346.     if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0)
  347.         error(pcap_geterr(pd));
  348.  
  349.     if (pcap_stats(pd, &stat) < 0)
  350.         (void)fprintf(stderr, "pcap_stats: %s\n",
  351.             pcap_geterr(pd));
  352.     else {
  353.         (void)fprintf(stderr, "%d packets received by filter\n",
  354.             stat.ps_recv);
  355.         (void)fprintf(stderr, "%d packets dropped by kernel\n",
  356.             stat.ps_drop);
  357.     }
  358.  
  359.     pcap_close(pd);
  360.  
  361.     exit(0);
  362. }
  363.  
  364. /* make a clean exit on interrupts */
  365. SIGRET
  366. cleanup(int signo)
  367. {
  368.     struct pcap_stat stat;
  369.  
  370.     (void)fflush(stdout);
  371.     putc('\n', stderr);
  372.     if (pcap_stats(pd, &stat) < 0)
  373.         (void)fprintf(stderr, "pcap_stats: %s\n",
  374.             pcap_geterr(pd));
  375.     else {
  376.         (void)fprintf(stderr, "%d packets received by filter\n",
  377.             stat.ps_recv);
  378.         (void)fprintf(stderr, "%d packets dropped by kernel\n",
  379.             stat.ps_drop);
  380.     }
  381.     exit(0);
  382. }
  383.  
  384. /* Like default_print() but data need not be aligned */
  385. void
  386. default_print_unaligned(register const u_char *cp, register int length)
  387. {
  388.     register u_int i, s;
  389.     register int nshorts;
  390.  
  391.     nshorts = (u_int) length / sizeof(u_short);
  392.     i = 0;
  393.     while (--nshorts >= 0) {
  394.         if ((i++ % 8) == 0)
  395.             (void)printf("\n\t\t\t");
  396.         s = *cp++;
  397.         (void)printf(" %02x%02x", s, *cp++);
  398.     }
  399.     if (length & 1) {
  400.         if ((i % 8) == 0)
  401.             (void)printf("\n\t\t\t");
  402.         (void)printf(" %02x", *cp);
  403.     }
  404. }
  405.  
  406. void
  407. default_print(register const u_char *bp, register int length)
  408. {
  409.     register const u_short *sp;
  410.     register u_int i;
  411.     register int nshorts;
  412.  
  413.     if ((int)bp & 1) {
  414.         default_print_unaligned(bp, length);
  415.         return;
  416.     }
  417.     sp = (u_short *)bp;
  418.     nshorts = (u_int) length / sizeof(u_short);
  419.     i = 0;
  420.     while (--nshorts >= 0) {
  421.         if ((i++ % 8) == 0)
  422.             (void)printf("\n\t\t\t");
  423.         (void)printf(" %04x", ntohs(*sp++));
  424.     }
  425.     if (length & 1) {
  426.         if ((i % 8) == 0)
  427.             (void)printf("\n\t\t\t");
  428.         (void)printf(" %02x", *(u_char *)sp);
  429.     }
  430. }
  431.  
  432. void
  433. usage()
  434. {
  435.     extern char version[];
  436.  
  437.     (void)fprintf(stderr, "Version %s\n", version);
  438.     (void)fprintf(stderr,
  439. "Usage: tcpdump [-dDeflnOpqtvx] [-c count] [-i interface]\n");
  440.     (void)fprintf(stderr,
  441. "\t\t[-r filename] [-w filename | -W filename] [expr]\n");
  442.     exit(-1);
  443. }
  444.